﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using DotNetNuke.Data;
using DotNetNuke.Data.PetaPoco;
using DotNetNuke.ComponentModel.DataAnnotations;
using DotNetNuke.Common.Utilities;

namespace DotNetNuke.Modules.mwOrgChart.Components.Business
{

    public class mwHierarchyController
    {

        //public static IEnumerable<mwHierarchy> Traverse(this IEnumerable<mwHierarchy> source, Func<mwHierarchy, bool> predicate)
        //{
        //    var traverse = Extensions.Y<IEnumerable<mwHierarchy>, IEnumerable<mwHierarchy>>(
        //        f => items =>
        //        {
        //            var r = new List<mwHierarchy>(items.Where(predicate));
        //            r.AddRange(items.SelectMany(i => f(i.Children)));
        //            return r;
        //        });

        //    return traverse(source);
        //}
    

        /// <summary>
        /// Gets the Hierarchy Tree
        /// </summary>
        /// <param name="HierarchyId">The Hierarchy Id</param>
        public static IEnumerable<mwHierarchy> GetHierarchy(int mwHierarchyID = 0)
        {
            IEnumerable<mwHierarchy> hierarchy;
            using (IDataContext ctx = DataContext.Instance())
            {
                var rep = ctx.GetRepository<mwHierarchy>();
                hierarchy = rep.Get().OrderBy(x => x.NodeOrder);

//                string rolesettingname = "mwRoleHierarchy_Setting";
                
//                string sql = @"
//                    SELECT   R.[RoleID]
//                            ,R.[RoleGroupID]
//                            ,RS.SettingValue as RoleParentID
//                            ,R.[RoleName]
//                            ,R.[Status]
//                            FROM [dnn702].[dbo].[Roles] R
//                            INNER JOIN {databaseOwner}{objectQualifier}[RoleGroups] RG
//                                ON R.RoleGroupID = RG.RoleGroupID
//                            INNER JOIN {databaseOwner}{objectQualifier}[RoleSettings] RS
//                                ON RS.RoleID = R.RoleID
//                            WHERE RS.SettingName = @0
//                            AND R.RoleGroupID = @1
//                    ";
//                roles = ctx.ExecuteQuery<OrgChartRole>(System.Data.CommandType.Text, sql, rolesettingname, mwRoleGroupHierarchyID);

            }
            return hierarchy;
        }

        public static IEnumerable<mwHierarchy> GetHierarchyChildren(int nodeId, int mwHierarchyID = 0)
        {
            IEnumerable<mwHierarchy> hierarchy;
            using (IDataContext ctx = DataContext.Instance())
            {
                //var rep = ctx.GetRepository<mwHierarchy>();
                //hierarchy = rep.Get().OrderBy(x => x.NodeOrder);


                //--AND PortalID = @PortalID
                //--AND r.RoleGroupID = @mwHierarchyRoleGroupID
                string sql = @";with CTE as
                                (
                                    SELECT 0 as LevelNum, H.NodeID, H.Name, 0 as ParentID
                                    FROM [dnn702].[dbo].[mwHierarchies] as H
                                    WHERE H.NodeID = @0
    
                                    UNION ALL
    
                                    SELECT (C.LevelNum + 1) as LevelNum, H.NodeID, H.Name, C.NodeID as ParentMemberID
                                    from [dnn702].[dbo].[mwHierarchies] as H
                                    join [dnn702].[dbo].[mwHierarchies] as HP
		                                on H.NodeID = HP.NodeID
                                    join CTE as C on C.NodeID = HP.ParentID   
                                )

                                SELECT * FROM CTE
                                ";
                hierarchy = ctx.ExecuteQuery<mwHierarchy>(System.Data.CommandType.Text, sql, nodeId);

            }
            return hierarchy;
        }

        /// <summary>
        /// Add a new Node
        /// </summary>
        /// <param name="node">The new Node</param>
        public static void AddNode(mwHierarchy node)
        {
            using (IDataContext ctx = DataContext.Instance())
            {
                var rep = ctx.GetRepository<mwHierarchy>();
                rep.Insert(node);
            }
        }

        /// <summary>
        /// Gets the Node.
        /// </summary>
        /// <param name="nodeId">The Node id.</param>
        /// <param name="portalId">The portal id.</param>
        /// <param name="ignoreCache">if set to <c>true</c> will get Node info directly from database.</param>
        /// <returns>Node info (mwHierarchy).</returns>
        public static mwHierarchy GetHierarchyNode(int nodeId, int portalId, bool ignoreCache)
        {
            mwHierarchy node;
            using (IDataContext ctx = DataContext.Instance())
            {
                var rep = ctx.GetRepository<mwHierarchy>();
                node = rep.GetById(nodeId);
                //node.Children = GetHierarchy(node.NodeID);
            }
            return node;

            ////if we are using the cache
            //if (ignoreCache) // || Host.Host.PerformanceSetting == Globals.PerformanceSettings.NoCaching)
            //{
            //    //tab = CBO.FillObject<TabInfo>(Provider.GetTab(roleId));
            //}
            //else
            //{
                //if we do not know the PortalId then try to find it in the Portals Dictionary using the TabId
                //portalId = GetPortalId(roleId, portalId);

                ////if we have the PortalId then try to get the TabInfo object
                //role = GetTabsByPortal(portalId).WithTabId(roleId) ??
                //      GetTabsByPortal(GetPortalId(roleId, Null.NullInteger)).WithTabId(roleId);

                //if (role == null)
                //{
                //    //recheck the info directly from database to make sure we can avoid error if the cache doesn't update
                //    // correctly, this may occurred when install is set up in web farm.
                //    tab = CBO.FillObject<TabInfo>(Provider.GetTab(roleId));

                //    // if tab is not null means that the cache doesn't update correctly, we need clear the cache
                //    // and let it rebuild cache when request next time.
                //    if (tab != null)
                //    {
                //        ClearCache(tab.PortalID);
                //    }
                //    else
                //    {
                //        Logger.WarnFormat("Unable to find tabId {0} of portal {1}", roleId, portalId);
                //    }
                //}
            //}

            
        }

        /// <summary>
        /// Move the Node after a selected Node in the list
        /// </summary>
        /// <param name="node">Node to move</param>
        /// <param name="targetNodeId">Node Target id</param>
        public void MoveNodeAfter(mwHierarchy node, int targetNodeId)
        {
            PetaPocoHelper.ExecuteNonQuery(DotNetNuke.Common.Utilities.Config.GetConnectionString(), System.Data.CommandType.StoredProcedure, "mwMoveNodeAfter", node.NodeID, targetNodeId);
        }

        /// <summary>
        /// Move the Node before a selected Node in the list
        /// </summary>
        /// <param name="node">Node to move</param>
        /// <param name="targetNodeId">Node Target id</param>
        public void MoveNodeBefore(mwHierarchy node, int targetNodeId)
        {
            PetaPocoHelper.ExecuteNonQuery(DotNetNuke.Common.Utilities.Config.GetConnectionString(), System.Data.CommandType.StoredProcedure, "mwMoveNodeBefore", node.NodeID, targetNodeId);
        }

        /// <summary>
        /// Move the Node to a selected Node as child
        /// </summary>
        /// <param name="node">Node to move</param>
        /// <param name="targetNodeId">Node Target id</param>
        public void MoveNodeToParent(mwHierarchy node, int targetNodeId)
        {
            PetaPocoHelper.ExecuteNonQuery(DotNetNuke.Common.Utilities.Config.GetConnectionString(), System.Data.CommandType.StoredProcedure, "mwMoveNodeToParent", node.NodeID, targetNodeId);
        }
    }
}